package com.example.pluginmanager.git;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.pluginmanager.maven.MavenUtil;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.*;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GitUtil {

    @Autowired
    private MavenUtil mavenUtil;

    //获取指定账号下的所有项目
    public void getAllProjectByUser() {
        HttpRequest request = HttpUtil.createGet("http://gitcbu.sso360.cn:8888/api/v4/projects").header("PRIVATE-TOKEN", "BS7PX5r7jxMBsVZYaCAf");
        HttpResponse execute = request.execute();
        String body = execute.body();
        JSONArray objects = JSONUtil.parseArray(body);
        List<JSONObject> jsonObjects = objects.toList(JSONObject.class);

        //TODO 过滤出我这一个项目,后面去掉
        List<JSONObject> id1 = jsonObjects.stream().filter(jsonObject -> {
            return jsonObject.getStr("id").equals("4239");
        }).collect(Collectors.toList());

        id1.forEach(jsonObject -> {
            String id = jsonObject.getStr("id");
            log.info("项目id: {}", id);
            String http_url_to_repo = jsonObject.getStr("http_url_to_repo");
            log.info("仓库地址:{}", http_url_to_repo);
            String projectName = jsonObject.getStr("name");
            log.info("默认分支:{}", jsonObject.getStr("default_branch"));

            getProjectAllBranch(http_url_to_repo, id, projectName);
        });
    }


    //获取指定项目下的所有分支
    public void getProjectAllBranch(String repo, String projectId, String projectName) {
        HashSet<String> strings = new HashSet<>();

        HttpRequest request = HttpUtil.createGet("http://gitcbu.sso360.cn:8888/api/v4/projects/" + projectId + "/repository/branches").header("PRIVATE-TOKEN", "BS7PX5r7jxMBsVZYaCAf");
        HttpResponse execute = request.execute();
        String body = execute.body();
        JSONArray objects = JSONUtil.parseArray(body);
        //所有分支
        List<JSONObject> jsonObjects = objects.toList(JSONObject.class);

        jsonObjects.forEach(jsonObject -> {
            String branchName = jsonObject.getStr("name");
            log.info("分支名: {}", branchName);
            JSONObject commit = jsonObject.getJSONObject("commit");
            String id = commit.getStr("id");
            log.info("commit id:{}", id);
            String message = commit.getStr("message");
            log.info("commit message:{}", message);

            //TODO 获取此分支的插件的所有commit , commitId入库 ,每次判断commitId是否存在,存在则证明这次已经打包过,不再打包
            // 并且判断message是否以指定字符开头,是则拉取打包


            //获取当前分支下的commit
            HttpRequest request2 = HttpUtil.createGet("http://gitcbu.sso360.cn:8888/api/v4/projects/" + projectId + "/repository/commits?ref_name=" + branchName).header("PRIVATE-TOKEN", "BS7PX5r7jxMBsVZYaCAf");
            HttpResponse execute2 = request2.execute();
            String body2 = execute2.body();
            JSONArray objects2 = JSONUtil.parseArray(body2);
            //所有分支的commit信息
            List<JSONObject> allCommits = objects2.toList(JSONObject.class);
            //TODO 按照commit时间降序

            allCommits.forEach(commits -> {
                //TODO 先判断commit的message是否以指定字符开头
                String message1 = commits.getStr("message");
                String commitId = commits.getStr("id");

                //TODO 指定文字开头  && message1.startsWith("package ")
                if (StrUtil.isNotEmpty(message1) && message1.startsWith("push2 ")) {
                    //TODO 查询数据库,判断commitId是否存在,存在则为旧的已提交的,不用打包
                    // if(commitId != null){
                    // }
                    //不存在,则clone 或者 pull
                    try {
                        //TODO 第一次clone,将项目id+分支名作为唯一建入库,下次如果发现有此项目,都改为 pull 命令
//                        if (!(projectId + branchName).equals("4239master")) {
                        if (!strings.contains(projectId+branchName)){
                            //判断 项目id+分支名 在数据库是否存在,存在则pull,否则clone
                            cloneProject(repo, branchName, projectName);
                            log.info("=======clone===========");
                            strings.add(projectId + branchName);
                        } else {
                            log.info("=======pull===========");
                            pullProject(repo, branchName, projectName, commitId);
                        }
                    } catch (GitAPIException e) {
                        e.printStackTrace();
                        throw new RuntimeException("clone 出错");
                    }
                }
            });
        });
    }

    /**
     * git clone单个项目
     *
     * @param httpRepo    项目仓库地址
     * @param projectName 项目名(一个项目下有多个分支,统一在一个文件夹下)
     * @throws GitAPIException
     * @Param branch 分支名
     */
    public void cloneProject(String httpRepo, String branch, String projectName) throws GitAPIException {

        //TODO clone完将 项目id+分支名 存入数据库,作为唯一,判断下次是clone还是pull
        Git result = Git.cloneRepository()
                .setURI(httpRepo)
                .setDirectory(new File("D://jGitTest//" + projectName + "//" + branch + "//"))
                .setBranch(branch)
                .setCredentialsProvider(new UsernamePasswordCredentialsProvider("chenli", "chenli0403"))
                .call();
//
//        Repository repository = result.getRepository();

        //TODO maven打包
        mavenUtil.operationMavenOrder("D:\\maven\\apache-maven-3.8.4-bin\\apache-maven-3.8.4", "D://jGitTest//" + projectName + "//" + branch + "//pom.xml", "clean package", "D://jGitTest//" + projectName + "//" + branch + "//target//");
    }


    /**
     * git pull单个项目
     *
     * @param httpRepo    项目仓库地址
     * @param projectName 项目名(一个项目下有多个分支,统一在一个文件夹下)
     * @throws GitAPIException
     * @Param branch 分支名
     */
    public void pullProject(String httpRepo, String branch, String projectName, String commitId) {
        //打开指定的git项目,直接进行 pull
        Git open = null;
        try {
            open = Git.open(new File("D://jGitTest//" + projectName + "//" + branch + "//.git"));
            open.checkout().setCreateBranch(false).setName(commitId).call();
        } catch (JGitInternalException | RepositoryNotFoundException gitExec) {
            log.error("checkout无此版本 :{}", gitExec.getMessage());
            try {
                log.info("尝试删除后 clone最新版本,进行checkout到指定commitId版本再打包");
                //必须先关闭上一个git,否则无法删除
                open.close();
                //递归删除子git文件和目录
                deleteFile("D://jGitTest//" + projectName + "//" + branch);
                Git result = Git.cloneRepository()
                        .setURI(httpRepo)
                        .setDirectory(new File("D://jGitTest//" + projectName + "//" + branch + "//"))
                        .setBranch(branch)
                        .setCredentialsProvider(new UsernamePasswordCredentialsProvider("chenli", "chenli0403"))
                        .call();
                result.checkout().setName(commitId).call();
            } catch (GitAPIException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("pull 项目错误");
        } catch (GitAPIException e) {
            e.printStackTrace();
        } finally {
            open.close();
        }

        //maven打包
        mavenUtil.operationMavenOrder("D:\\maven\\apache-maven-3.8.4-bin\\apache-maven-3.8.4", "D://jGitTest//" + projectName + "//" + branch + "//pom.xml", "clean package", "D://jGitTest//" + projectName + "//" + branch + "//target//");
    }


    /**
     * 递归删除子文件
     *
     * @param path 文件路径
     */
    public static void deleteFile(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] temp = file.listFiles(); //获取该文件夹下的所有文件
                for (File value : temp) {
                    deleteFile(value.getAbsolutePath());
                }
            } else {
                file.delete(); //删除子文件
            }
            file.delete(); //删除文件夹
        }
    }

}
